package config

import (
	"flag"
	"gitverse.ru/synapse/kubelatte/pkg/observability/logs"
	"gitverse.ru/synapse/kubelatte/pkg/util"
	"os"
	"strconv"

	"github.com/jessevdk/go-flags"
	"github.com/pkg/errors"
)

const (
	PodClusterName  = "POD_CLUSTER_NAME"
	ServerKey       = "SERVER_KEY"
	ServerCert      = "SERVER_CERT"
	SertCa          = "SERVER_CA"
	TLSPort         = "TLS_PORT"
	ScopeValidation = "KBLT_VALIDATION"
)

// WebhookConfig is the configuration parameters for the sidecar injector
type WebhookConfig struct {
	TLSPort                  int    `long:"port"  required:"false" description:"webhook server port for mutate endpoint"`
	HTTPPort                 int    `long:"http-port" default:"17773" required:"false" description:"webhook server http port for metrics and healthz endpoints"`
	CertFilePath             string `long:"cert-file-path" required:"false" description:"file containing the x509 Certificate for HTTPS"`
	KeyFilePath              string `long:"key-file-path" required:"false" description:"file containing the x509 private key"`
	CaFilePath               string `long:"ca-file-path" required:"false" description:"file containing the CA cert"`
	BuildInfoLabels          string `long:"build-info-labels" required:"false" description:"additional build info metric labels"`
	AllowDeprecatedTLSConfig bool   `long:"allow-deprecated-tls-config" required:"false" description:"permits use of deprecated TLS configuration (TLS 1.0/1.1, weak ciphers)"`
}

// NewWebhookConfig is a constructor for WebhookConfig
func NewWebhookConfig() (*WebhookConfig, error) {
	config, err := parse()
	if err != nil {
		return nil, errors.Errorf("api=NewWebhookConfig, reason=parse, err=%v", err)
	}
	return config, nil
}

// parse the args and environment to fill the ClientConfig
func parse() (*WebhookConfig, error) {
	c := &WebhookConfig{}
	parser := flags.NewParser(c, flags.HelpFlag|flags.PrintErrors|flags.PassDoubleDash|flags.IgnoreUnknown)

	extraArgs, err := parser.Parse()
	if err != nil {
		return nil, errors.Errorf("api=parse, err=%v", err)
	}

	if c.KeyFilePath == "" {
		c.KeyFilePath = os.Getenv(ServerKey)
	}
	if c.CertFilePath == "" {
		c.CertFilePath = os.Getenv(ServerCert)
	}

	if c.CaFilePath == "" {
		c.CaFilePath = os.Getenv(SertCa)
	}

	tlsPort := os.Getenv(TLSPort)
	if tlsPort != "" {
		p, err := strconv.Atoi(tlsPort)
		if err != nil {
			logs.Errorf("port: %s must by int number from 0 to 65535", tlsPort)
		} else {
			c.TLSPort = p
		}
	}

	// Parse any extra args for dependent packages that use "flag" (e.g., logs).
	flag.CommandLine.Parse(extraArgs)
	return c, nil
}

func Load() (*WebhookConfig, error) {

	util.StatusInfo = nil

	webhookConfig, err := NewWebhookConfig()
	if err != nil {
		return nil, err
	}

	var flagsErr *flags.Error
	if errors.As(err, &flagsErr) && errors.Is(flagsErr.Type, flags.ErrHelp) {
		return nil, err
	}

	return webhookConfig, nil
}
